<template>
    <div
        ref="waterfallWrapper"
        class="waterfall-list"
        :style="{ height: `${wrapperHeight}px` }"
    >
        <div
            v-for="(item, index) in list"
            :key="getKey(item, index)"
            class="waterfall-item"
            :style="{ '--col-width': colWidth }"
        >
            <div class="waterfall-card">
                <slot
                    name="item"
                    :item="item"
                    :index="index"
                ></slot>
            </div>
        </div>
    </div>
</template>

<script lang="ts">
import type { PropType } from 'vue'
import { defineComponent, watch } from 'vue'
import { useDebounceFn } from '@vueuse/core'
import { useCalculateCols, useLayout } from './use'
import type { ViewCard } from './types/waterfall'

export default defineComponent({
    props: {
        list: {
            type: Array as PropType<ViewCard[]>,
            default: () => []
        },
        rowKey: {
            type: String,
            default: 'id'
        },
        imgSelector: {
            type: String,
            default: 'src'
        },
        width: {
            type: Number,
            default: 200
        },
        breakpoints: {
            type: Object,
            default: () => ({
                1200: {
                    rowPerView: 3
                },
                800: {
                    rowPerView: 2
                },
                500: {
                    rowPerView: 1
                }
            })
        },
        gutter: {
            type: Number,
            default: 10
        },
        hasAroundGutter: {
            type: Boolean,
            default: true
        },
        animationPrefix: {
            type: String,
            default: 'animate__animated'
        },
        animationEffect: {
            type: String,
            default: 'fadeIn'
        },
        animationDuration: {
            type: Number,
            default: 1000
        },
        animationDelay: {
            type: Number,
            default: 300
        },
        backgroundColor: {
            type: String,
            default: '#fff'
        },
        delay: {
            type: Number,
            default: 300
        }
    },

    setup(props) {
        // 容器块信息
        const { waterfallWrapper, wrapperWidth, colWidth, cols, offsetX } = useCalculateCols(props)

        // 容器高度块定位
        const { wrapperHeight, layoutHandle } = useLayout(
            props,
            colWidth,
            cols,
            offsetX,
            waterfallWrapper
        )

        // 1s内最多执行一次排版,减少性能开销
        const renderer = useDebounceFn(() => {
            layoutHandle()
        }, props.delay)

        // 列表发生变化直接触发排版
        watch(
            () => [wrapperWidth, colWidth, props.list],
            () => {
                if (wrapperWidth.value > 0) {
                    renderer()
                }
            },
            { deep: true }
        )

        // 获取唯一值
        const getKey = (item: ViewCard, index: number): string => {
            return item[props.rowKey] || index
        }

        return {
            colWidth,
            waterfallWrapper,
            wrapperHeight,
            getKey,
            renderer
        }
    }
})
</script>

<style scoped>
.waterfall-list {
    position: relative;
    width: 100%;
    overflow: hidden;
    background-color: v-bind(background-color);
}
.waterfall-item {
    position: absolute;
    top: 0;
    left: 0;
    visibility: hidden;
    transform: translate3d(0, 3000px, 0);
}

/* 初始的入场效果 */
@keyframes fadeIn {
    0% { opacity: 0; }
    100% { opacity: 1;  }
}

@keyframes fadeIn {
    0% { opacity: 0; }
    100% { opacity: 1; }
}

.fadeIn {
    animation-name: fadeIn;
}
</style>